package com.itheima.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.support.spring.annotation.FastJsonView;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.entity.QueryPageBean;
import com.itheima.mapper.PermissionMapper;
import com.itheima.mapper.RoleMapper;
import com.itheima.mapper.UserMapper;
import com.itheima.pojo.CheckItem;
import com.itheima.pojo.Permission;
import com.itheima.pojo.Role;
import com.itheima.pojo.User;
import com.itheima.service.UserService;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
@Transactional
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    @Autowired
    RoleMapper roleMapper;

    @Autowired
    PermissionMapper permissionMapper;

    @Autowired
    RedisTemplate redisTemplate;

    @Autowired
    UserMapper userMapper;

    @Override // 此方法用作数据库版登陆校验
    public User findUserByUsername(String username) {
        //redis process
        Object userRedis = redisTemplate.opsForValue().get("User"+username);
        if(userRedis == null){
            //mysql process
            QueryWrapper<User> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("username",username);
            User user = baseMapper.selectOne(queryWrapper);
            if (user!=null) {
                Integer userId = user.getId();
                List<Role> roles = roleMapper.findRolesByUserId(userId);
                for (Role role : roles) {
                    Integer roleId = role.getId();
                    List<Permission> permissions = permissionMapper.findPermissionsByRoleId(roleId);
                    role.setPermissions(permissions);
                }
                user.setRoles(roles);
            }
            redisTemplate.opsForValue().set("User"+user.getUsername(),user);
            final Object userForRedisView = redisTemplate.opsForValue().get("UserForView"+user.getUsername());
            redisTemplate.opsForValue().set("UserForView",userForRedisView);
            return user;
        }else {
            final String userRedisStr = JSON.toJSONString(userRedis);
            final User redisUser  = JSON.parseObject(userRedisStr, User.class);
            final Object userForRedisView = redisTemplate.opsForValue().get("UserForView"+redisUser.getUsername());
            redisTemplate.opsForValue().set("UserForView",userForRedisView);
            return redisUser;
        }
    }

    @Override // 此方法用作修改权限登录密码
    public void changePassword(String username, String password) {
        final Object user = redisTemplate.opsForValue().get("User"+username);
        final String userStr = JSON.toJSONString(user);
        final User userRes = JSON.parseObject(userStr, User.class);
        User userForRedisView = new User();
        userForRedisView.setPassword(password);
        userForRedisView.setUsername(username);
        redisTemplate.opsForValue().set("UserForView"+username,userForRedisView);
        String encode = new BCryptPasswordEncoder().encode(password);
        userRes.setPassword(encode);
        redisTemplate.opsForValue().set("User"+username,userRes);
        baseMapper.changePasswordByUsername(username,encode);
    }

    @Override
    public Map<String, Object> backViewForLogin() {
        HashMap<String,Object> map = new HashMap<>();
        Object user = redisTemplate.opsForValue().get("UserForView");
        final String userStr = JSON.toJSONString(user);
        User userForVIew = JSON.parseObject(userStr,User.class);
        if(userForVIew!=null){
            map.put("username",userForVIew.getUsername());
            final String password = userForVIew.getPassword();
            map.put("password",password);
            return map;
        }else {
            return null;
        }
    }

    @Override
    public Map findPage(QueryPageBean queryPageBean) {
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        String queryString = queryPageBean.getQueryString();
        userQueryWrapper.like("username",queryString==null?"":queryString);
        Page<User> page = page(new Page<User>(queryPageBean.getCurrentPage(), queryPageBean.getPageSize()), userQueryWrapper);
        HashMap<String, Object> map = new HashMap<>();
        map.put("total",page.getTotal());
        map.put("records",page.getRecords());
        return map;
    }

    @Override
    public void deleteUserById(Integer id) {
        userMapper.deleteUserById(id);
        QueryWrapper<User> queryWrapper = new QueryWrapper();
        queryWrapper.eq("id",id);
        final User user = userMapper.selectOne(queryWrapper);
        if(user!=null) {
            redisTemplate.delete("User" + user.getUsername());
            redisTemplate.delete("UserForView"+user.getUsername());
        }
    }

    @Override
    public void saveOrUpdateByUser(User user) {
        User userForRedisview= new User();
        userForRedisview.setUsername(user.getUsername());
        userForRedisview.setPassword(user.getPassword());
        redisTemplate.opsForValue().set("UserForView"+user.getUsername(),userForRedisview);
        final String encodePassword = new BCryptPasswordEncoder().encode(user.getPassword());
        user.setPassword(encodePassword);
        redisTemplate.delete("User" + user.getUsername());
        saveOrUpdate(user);
    }
}
